package com.xiaomi.rocketMQ.consumer;

import com.alibaba.fastjson.JSON;
import com.xiaomi.entity.*;
import com.xiaomi.service.AlertService;
import com.xiaomi.service.RuleService;
import com.xiaomi.service.VehicleService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import org.apache.rocketmq.common.message.MessageExt;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.List;

@Slf4j
@Component
public class BatteryWarnConsumer{
    @Autowired
    private RuleService ruleService;
    @Autowired
    private AlertService alertService;
    @Autowired
    private VehicleService vehicleService;
    @Autowired
    private RedisTemplate<String,Object> redisTemplate;
    private final DefaultMQPushConsumer consumer;

    public BatteryWarnConsumer() {
        this.consumer = new DefaultMQPushConsumer("battery_consumer_group");
    }

    @PostConstruct
    public void init() throws Exception {
        // 配置消费者参数
        consumer.setNamesrvAddr("localhost:9876"); // 修改为实际NameServer地址
        consumer.subscribe("BATTERY_WARN_TOPIC", "*"); // 订阅主题和标签

        // 注册消息监听器
        consumer.registerMessageListener((MessageListenerConcurrently) (msgs, context) -> {
            msgs.forEach(message -> {
                try {
                    String msgBody = new String(message.getBody(), StandardCharsets.UTF_8);
                    // 直接打印消息内容
                    log.info("【收到消息】{}", msgBody);

                    //解析json格式数据得到Signal对象
                    Signal signal = JSON.parseObject(msgBody, Signal.class);

                    //根据Signal的汽车的电池类型得到rules
                    String batteryType = vehicleService.getById(signal.getVehicleFrameNumber()).getBatteryType();
                    List<Rule> rules = ruleService.getRulesByBatteryType(batteryType);

                    //找出当前信息对应的汽车的最大最小电压电流值
                    String maxVoltageKey = "car:" + signal.getVehicleFrameNumber() + ":max_voltage";
                    String minVoltageKey = "car:" + signal.getVehicleFrameNumber() + ":min_voltage";
                    String maxCurrentKey = "car:" + signal.getVehicleFrameNumber() + ":max_current";
                    String minCurrentKey = "car:" + signal.getVehicleFrameNumber() + ":min_current";
                    Double maxVoltage = (Double) redisTemplate.opsForValue().get(maxVoltageKey);
                    Double minVoltage = (Double) redisTemplate.opsForValue().get(minVoltageKey);
                    Double maxCurrent = (Double) redisTemplate.opsForValue().get(maxCurrentKey);
                    Double minCurrent = (Double) redisTemplate.opsForValue().get(minCurrentKey);

                    // 处理电压差报警规则
                    processVoltageRule(rules, signal, maxVoltage, minVoltage);

                    // 处理电流差报警规则
                    processCurrentRule(rules, signal, maxCurrent, minCurrent);

                } catch (Exception e) {
                    log.error("消息解析失败", e);
                }
            });
            return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
        });

        consumer.start();
        log.info("RocketMQ消费者已启动");
    }



    private void processVoltageRule(List<Rule> rules, Signal signal, Double maxVoltage, Double minVoltage) {
        rules.stream()
                .filter(rule -> rule.getRuleCode() == 1)
                .findFirst()
                .ifPresent(rule -> {
                    //解析ConditionJson
                    Condition condition = JSON.parseObject(rule.getConditionJson(), Condition.class);

                    //计算实际的电压差
                    Double voltageDiff = maxVoltage-minVoltage;

                    //匹配等级
                    int level = matchThreshold(condition.getThresholds(), voltageDiff);
                    if (level > 0) {
                        // 发送报警信息
                        saveAlertRecord(signal, rule, level);
                    }
                });
    }
    private void processCurrentRule(List<Rule> rules, Signal signal, Double maxCurrent, Double minCurrent) {
        rules.stream()
                .filter(rule -> rule.getRuleCode() == 2)
                .findFirst()
                .ifPresent(rule -> {
                    //解析ConditionJson
                    Condition condition = JSON.parseObject(rule.getConditionJson(), Condition.class);

                    //计算实际的电流差
                    Double currentDiff = maxCurrent-minCurrent;

                    //匹配等级
                    int level = matchThreshold(condition.getThresholds(), currentDiff);
                    if (level > 0) {
                        // 发送报警信息
                        saveAlertRecord(signal, rule, level);
                    }
                });
    }

    private int matchThreshold(List<Threshold> thresholds, Double value) {
        //按照min降序排列（确保先匹配高优先级规则）
        thresholds.sort((t1,t2) -> Double.compare(t2.getMin(), t1.getMin()));

        for (Threshold threshold : thresholds) {
            if(threshold.getMax()!=null){
                if (value >= threshold.getMin() && value <= threshold.getMax()) {
                    return threshold.getLevel();
                }
            }else {
                if (value >= threshold.getMin())
                    return threshold.getLevel();
            }
        }
        return 0;
    }
    private void saveAlertRecord(Signal signal, Rule rule, int level) {
        String ruleName = rule.getRuleName();
        AlertRecord alert = AlertRecord.builder()
                .vehicleFrameNumber(signal.getVehicleFrameNumber())
                .ruleCode(rule.getRuleCode())
                .alertLevel(level)
                .alertTime(LocalDateTime.now())
                .build();
        alertService.save(alert);
        log.info("【生成预警记录】车架号:{} 规则:{} 等级:{}",
                signal.getVehicleFrameNumber(), ruleName, level);
    }
}